package cn.y.operation.framework.utils.dev;

import cn.y.operation.framework.constants.Constants;
import cn.y.operation.framework.enums.ContentTypeEnum;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.reflect.FieldUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.cglib.beans.BeanMap;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CommonUtils {

    public static DecimalFormat decimalFormat = new DecimalFormat("#.##");
    public static SimpleDateFormat isoDatetimeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
    public static ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 将一个对象数组转换为另一个类型的数组
     *
     * @param arr
     * @param convertClass
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T[] convertTo(Object[] arr, Class<T> convertClass) {
        if (arr == null || arr.length == 0) {
            return (T[]) Array.newInstance(convertClass, 0);
        }
        T[] arrResult = (T[]) Array.newInstance(convertClass, arr.length);

        if (convertClass == String.class) {
            for (int i = 0; i < arr.length; i++) {
                arrResult[i] = (T) arr[i].toString();
            }
        } else if (convertClass == Long.class) {
            for (int i = 0; i < arr.length; i++) {
                arrResult[i] = (T) new Long(arr[i].toString());
            }
        } else if (convertClass == Integer.class) {
            for (int i = 0; i < arr.length; i++) {
                arrResult[i] = (T) new Integer(arr[i].toString());
            }
        } else if (convertClass == Boolean.class) {
            for (int i = 0; i < arr.length; i++) {
                arrResult[i] = (T) new Boolean(arr[i].toString());
            }
        } else {
            throw new UnsupportedOperationException("Unsupported Class '" + convertClass.getName() + "'");
        }
        return arrResult;
    }


    /**
     * 获取日期的最小时间 形如： 2016-12-12 00:00:00.0
     */
    public static Date getMinTime(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = DateUtils.toCalendar(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获取日期的最大时间 形如： 2016-12-12 23:59:59.999
     */
    public static Date getMaxTime(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = DateUtils.toCalendar(date);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return calendar.getTime();
    }

    /**
     * 对象转换为json字符串
     */
    public static String toJSON(Object obj, boolean ignoreNull) {
        try {
            if (obj == null) {
                return null;
            }
            objectMapper.setSerializationInclusion(ignoreNull ? Include.NON_NULL : Include.ALWAYS);
            return objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 对象转换为json字符串
     *
     * @param <T>
     */
    public static <T> T jsonToObj(Class<T> clazz, String content, String dateFormat) {
        try {
            if (StringUtils.isEmpty(content)) {
                return null;
            }
            SimpleDateFormat format = new SimpleDateFormat(StringUtils.defaultIfEmpty(dateFormat, Constants.YYYY_MM_DDHHMMSS));
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
            objectMapper.getDeserializationConfig().with(format);
            return objectMapper.readValue(content, clazz);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 数组转换为json字符串
     *
     * @param <T>
     */
    public static <T> List<T> jsonToList(Class<T> clazz, String content, String dateFormat) {
        try {
            if (StringUtils.isEmpty(content)) {
                return Collections.emptyList();
            }
            SimpleDateFormat format = new SimpleDateFormat(StringUtils.defaultIfEmpty(dateFormat, Constants.YYYY_MM_DDHHMMSS));
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
            objectMapper.getDeserializationConfig().with(format);
            return objectMapper.readValue(content, TypeFactory.defaultInstance().constructCollectionType(List.class, clazz));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 日期格式化
     *
     * @param date
     * @return
     */
    public static String formatDate(Date date, String pattern) {
        if (date != null) {
            return DateFormatUtils.format(date, pattern != null ? pattern : Constants.YYYY_MM_DDHHMMSS);
        }
        return null;
    }

    /**
     * 日期格式化
     *
     * @param date
     * @return yyyy-MM-dd HH:mm:ss
     */
    public static String formatDate(Date date) {
        if (date == null) {
            return "";
        }
        return formatDate(date, Constants.YYYY_MM_DDHHMMSS);
    }

    /**
     * 日期格式化
     *
     * @param pattern
     * @return new Date() yyyy-MM-dd HH:mm:ss
     */
    public static String formatDate(String pattern) {
        return DateFormatUtils.format(new Date(), pattern != null ? pattern : Constants.YYYY_MM_DDHHMMSS);
    }

    public static String getDateStr_YMD(Date date) {
        DateFormat df = new SimpleDateFormat("yyyyMMdd");
        return df.format(date);
    }

    /**
     * 将日期字符串转为日期
     *
     * @param dateStr
     * @return
     */
    public static Date parseDateZh(String dateStr, String fomatStr) {
        try {
            if (StringUtils.isEmpty(dateStr)) {
                return null;
            }
            DateFormat df = new SimpleDateFormat(fomatStr);
            Date date = df.parse(dateStr);
            return date;
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 将时间戳转为日期格式
     *
     * @return
     */
    public static Date parseDate(Long millis) {
        try {
            Calendar instants = Calendar.getInstance();
            instants.setTimeInMillis(millis);
            return instants.getTime();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 格式化 ISO时间yyyy-MM-dd'T'HH:mm:ss 为 UTC时间
     *
     * @param ISODate
     * @return yyyy-MM-dd HH:mm:ss
     */
    public static String formatUTC(String ISODate) {
        try {
            isoDatetimeFormat.setTimeZone(DateUtils.UTC_TIME_ZONE);
            return formatDate(isoDatetimeFormat.parse(ISODate));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 时间格式化输出 如 ：5分钟内
     */
    public static String prettyDate(Date date) {
        String output = "";
        if (date == null) {
            return output;
        }
        long result = System.currentTimeMillis() - date.getTime();
        if (result < 60000) {// 一分钟内
            output = "刚刚";
        } else if (result < 3600000) {// 一小时内
            long seconds = result / 60000;
            output = seconds + "分钟前";
        } else if (result < 86400000) {// 一天内
            long seconds = result / 3600000;
            output = seconds + "小时前";
        } else if (result < 604800000) {// 7天内
            long seconds = result / 86400000;
            output = seconds + "天前";
        } else {
            output = DateFormatUtils.format(date, Constants.YYYY_MM_DDHHMM);
        }
        return output;
    }

    /**
     * 格式化输出数字，如10000 ->  10K
     */
    public static String prettyNumber(double number) {
        if (number >= 1000L) {
            return decimalFormat.format(number / 1000L) + "K";
        }
        return decimalFormat.format(number);
    }

    /**
     * 将参数正向排序,并组成a=xx&b=xxx的形式
     */
    @SuppressWarnings("unchecked")
    public static String sortParam(Object param) {
        if (param == null) {
            return null;
        }
        StringBuffer buffer = new StringBuffer();
        Map<String, Object> sortedMap = new TreeMap<String, Object>(BeanMap.create(param));
        for (Map.Entry<String, Object> entry : sortedMap.entrySet()) {
            if (entry.getValue() != null && !"".equals(entry.getValue())) {
                buffer.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
        }
        return buffer.substring(0, buffer.length() - 1);
    }

    /**
     * 清空map
     *
     * @param paramMap
     */
    public static void clearMap(Map<?, ?>... paramMap) {
        if (paramMap == null) {
            return;
        }
        for (Map<?, ?> map : paramMap) {
            try {
                map.clear();
                map = null;
            } catch (Exception e) {
                //ignore
            }
        }
        paramMap = null;
    }

    /**
     * 清空collection
     *
     * @param paramCollection
     */
    public static void clearCollection(Collection<?>... paramCollection) {
        if (paramCollection == null) {
            return;
        }
        for (Collection<?> collection : paramCollection) {
            try {
                collection.clear();
                collection = null;
            } catch (Exception e) {
                //ignore
            }
        }
        paramCollection = null;
    }

    /**
     * 将bean转换成map 并根据字段名ASCII码值排序
     *
     * @param bean
     * @param containsSuperField      是否包含父类字段
     * @param containsEmptyValueField 是否包含空值字段
     * @return
     * @throws Exception
     */
    public static Map<String, Object> beanToMap(Object bean,
                                                boolean containsSuperField, boolean containsEmptyValueField) {
        if (bean == null) {
            return Collections.emptyMap();
        }
        List<Field> fields = getAllFieldsList(bean.getClass(), containsSuperField);
        if (CollectionUtils.isEmpty(fields)) {
            return Collections.emptyMap();
        }
        Map<String, Object> fieldMap = new HashMap<>(fields.size());
        for (Field field : fields) {
            if (Modifier.isTransient(field.getModifiers())) {
                continue;
            }
            Object fieldValue = null;
            try {
                fieldValue = FieldUtils.readField(field, bean, true);
            } catch (IllegalAccessException e) {
                //ignore
            }
            if (containsEmptyValueField) {
                fieldMap.put(field.getName(), fieldValue);
            } else {
                if (fieldValue != null) {
                    fieldMap.put(field.getName(), fieldValue);
                }
            }
        }
        return fieldMap;
    }

    /**
     * 获取类的所有字段包括父类
     *
     * @param cls
     * @return
     */
    public static List<Field> getAllFieldsList(Class<?> cls, boolean containsSuperField) {
        if (cls == null) {
            return Collections.emptyList();
        }
        if (containsSuperField) {
            List<Field> allFields = new ArrayList<Field>();
            Class<?> currentClass = cls;
            while (currentClass != null) {
                Field[] declaredFields = currentClass.getDeclaredFields();
                for (Field field : declaredFields) {
                    allFields.add(field);
                }
                currentClass = currentClass.getSuperclass();
            }
            return allFields;
        }
        return Arrays.asList(cls.getDeclaredFields());
    }

    public static String getTimestamp() {
        Long time = Calendar.getInstance().getTimeInMillis();
        int random = (int) ((Math.random() * 9 + 1) * 10000);
        return random + time.toString();
    }

    /**
     * 将字符串驼峰转为下划线
     *
     * @param param
     * @return
     */
    public static String changeToDatabaseColumn(String param) {
        Pattern p = Pattern.compile("[A-Z]");
        if (StringUtils.isEmpty(param)) {
            return "";
        }
        StringBuilder builder = new StringBuilder(param);
        Matcher mc = p.matcher(param);
        int i = 0;
        while (mc.find()) {
            builder.replace(mc.start() + i, mc.end() + i, "_" + mc.group().toLowerCase());
            i++;
        }
        if ('_' == builder.charAt(0)) {
            builder.deleteCharAt(0);
        }
        return builder.toString().toUpperCase();
    }


    public static String StringHide(String str) {
        if (StringUtils.isEmpty(str)) {
            return "";
        }
        String temp = "";
        if (str.length() > 12) {//前后显示四位、中间替换为*
            for (int i = 0; i < str.length() - 8; i++) {
                temp += "*";
            }
            return str.substring(0, 4) + temp + str.substring(str.length() - 4);
        } else if (str.length() > 8) {
            for (int i = 0; i < str.length() - 4; i++) {
                temp += "*";
            }
            return temp + str.substring(str.length() - 4);
        } else if (str.length() > 6) {
            for (int i = 0; i < str.length() - 2; i++) {
                temp += "*";
            }
            return temp + str.substring(str.length() - 2);
        } else {
            for (int i = 0; i < str.length(); i++) {
                temp += "*";
            }
            return temp;
        }
    }

    /**
     * 根据文件路径获取content-type
     */
    public static String getContentType(String objectKey) {
        if (StringUtils.isEmpty(objectKey)) {
            return "";
        }
        if (objectKey.lastIndexOf(".") < 0) {
            return ContentTypeEnum.UNKNOWN.getDisplayName();
        }
        String fileExtend = objectKey.substring(objectKey.lastIndexOf(".")).toLowerCase();
        System.out.println(fileExtend);
        ContentTypeEnum typeEnum = ContentTypeEnum.getEnum(fileExtend);
        if (typeEnum == null) {
            return ContentTypeEnum.UNKNOWN.getDisplayName();
        } else {
            return typeEnum.getDisplayName();
        }
    }

    public static String getVersion(String version, String binVersion) {
        if (StringUtils.isEmpty(version)) {
            return "";
        }
        if (StringUtils.isNotEmpty(binVersion) && version.length() > binVersion.length()) {
            return version.substring(0, binVersion.length()).toLowerCase();
        }
        return version.toLowerCase();
    }

    public static Long parseLong(String s) {
        try {
            if (StringUtils.isEmpty(s)) {
                return null;
            }
            return Long.parseLong(s);
        } catch (NumberFormatException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void main(String[] args) {
        System.out.println(getVersion("V2.3.6095.02-m - 20200803 23:23:02", "V2.3.6097"));
    }
}
